home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2008 March / PCgo 2008-03 (CD).iso / interface / static / Webde_SmartInstall.exe / kostenprotokoll_js / kostenprotokoll.js < prev   
Encoding:
JavaScript  |  2007-11-09  |  32.5 KB  |  973 lines

  1. var webde           = webde          ? webde :            {};
  2.     webde.dienste   = webde.dienste  ? webde.dienste :    {};
  3.  
  4. webde.dienste.kostenprotokoll = function() {
  5.     var that = this;    // used for anonymous functions (threading) and to give private methods access to object properties
  6.     
  7.     /**
  8.      * Map datastore fields to human readable labels
  9.      */
  10.     var datastoreFields = {
  11.         ca_User : 0,
  12.         r_Costs : 1,
  13.         d_Begin : 2,
  14.         i_Duration : 3,
  15.         i_DurationInSec: 4,
  16.         ca_Provider : 5,
  17.         i_Clock : 6,
  18.         r_CostPerMin : 7,
  19.         ca_TariffName : 8,
  20.         ca_PhoneNumber : 9,
  21.         r_CostPerCall : 10,
  22.         b_ChannelBundeled : 11,
  23.         i_UserId : 12                
  24.     };
  25.     
  26.     this.sortBy                     = 'd_Begin';  // contains the sort column
  27.     this.sortDirection              = {           // contains the sort direction for each column
  28.         d_Begin:         'desc',
  29.         i_DurationInSec: 'desc',
  30.         i_Clock:         'desc',
  31.         r_CostPerMin:    'desc',
  32.         r_CostPerCall:   'desc',
  33.         ca_Provider:     'desc',
  34.         ca_PhoneNumber:  'desc',
  35.         r_Costs:         'desc'
  36.     };
  37.     this.criticalDatastoreLength    = 300; // if datastore has more entries than this number show the modal panel
  38.     this.sum                        = 0;   // holds the sum for the chosen entries
  39.     this.duration                   = 0;   // holds the connection duration for the chosen entries
  40.     this.minDate                    = '';
  41.     this.minDisplayDate             = '';
  42.     this.maxDate                    = '';
  43.     this.tdMotherObj                = document.createElement('TD');
  44.     this.trMotherObj                = document.createElement('TR');
  45.     this.displayedResults           = 0;   // Number of displayed results
  46.     this.datastoreLength             = 0;   // Number of fields in the datastore
  47.  
  48.     // HTML Object names: IDs of HTML elements used for displaying information
  49.     this.HTMLObjectNames = {
  50.         list:               'Output',
  51.         modalPanelBG:       'ModalBG',
  52.         modalPanel:         'ModalPanel',
  53.         modalPanelStatus:   'ModalPanelTxt',
  54.         sum:                'Sum',
  55.         selector:           'Connections',
  56.         duration:           'Duration',
  57.         dateFrom:           'DateFrom',
  58.         dateTo:             'DateTo',
  59.         fulltext:           'Fulltext',
  60.         notification:       'NoResultNotification',
  61.         notificationH:      'NotificationH',
  62.         notificationTxt:    'NotificationTxt',
  63.         listTable:          'ListTable',
  64.         CSVArea:            'CSVArea',
  65.         CSVBox:             'CSVBox',
  66.         CSVTextarea:        'CSVTextarea'
  67.     };
  68.     
  69.     // -------------------------------------------------------------------------
  70.     // Private methods:
  71.     // -------------------------------------------------------------------------
  72.     
  73.     /**
  74.      * Constructor
  75.      *
  76.      * Get HTML-Objects and init values
  77.      */
  78.     function _init() {
  79.         that.listObj                = document.getElementById(that.HTMLObjectNames.list);
  80.         that.modalPanelBGObj        = document.getElementById(that.HTMLObjectNames.modalPanelBG);
  81.         that.modalPanelObj          = document.getElementById(that.HTMLObjectNames.modalPanel);
  82.         that.modalPanelStatusObj    = document.getElementById(that.HTMLObjectNames.modalPanelStatus);
  83.         that.sumObj                 = document.getElementById(that.HTMLObjectNames.sum);
  84.         that.durationObj            = document.getElementById(that.HTMLObjectNames.duration);
  85.         that.selectorObj            = document.getElementById(that.HTMLObjectNames.selector);
  86.         that.dateFromObj            = document.getElementById(that.HTMLObjectNames.dateFrom);
  87.         that.dateToObj              = document.getElementById(that.HTMLObjectNames.dateTo);
  88.         that.fulltextObj            = document.getElementById(that.HTMLObjectNames.fulltext);
  89.         that.noctificationObj       = document.getElementById(that.HTMLObjectNames.notification);
  90.         that.noctificationHObj      = document.getElementById(that.HTMLObjectNames.notificationH);
  91.         that.noctificationTxtObj    = document.getElementById(that.HTMLObjectNames.notificationTxt);
  92.         that.listTableObj           = document.getElementById(that.HTMLObjectNames.listTable);
  93.         that.CSVAreaObj             = document.getElementById(that.HTMLObjectNames.CSVArea);
  94.         that.CSVBox                 = document.getElementById(that.HTMLObjectNames.CSVBox);
  95.         that.CSVTextarea            = document.getElementById(that.HTMLObjectNames.CSVTextarea);
  96.         
  97.         that.pPrepareDatastore();
  98.         
  99.         if (typeof datastore === 'object' &&
  100.             datastore[0]) {
  101.             that.datastoreLength = datastore[0].length;     
  102.         }
  103.         
  104.         if (document.getElementById) {
  105.             _setInitialStartDate();
  106.             that.pPrintDates();
  107.             that.pSort('d_Begin');
  108.             that.pSelect();
  109.         }
  110.     }
  111.  
  112.     /**
  113.      * Create a Table row object
  114.      *
  115.      * @param {array} values for TD-Elements
  116.      * @param {string} classname: classname of TR-Element
  117.      * @return {object} DOM TR-Object
  118.      */
  119.     function _createTableRow(values, classname) {
  120.         var i;
  121.         var td_obj, txt_obj;
  122.         var tr_obj = that.trMotherObj.cloneNode(false);
  123.         var classNames = [ 'l', 'l', 'l', 'r', 'r', 'r', 'l', 'r' ];
  124.         
  125.         // Set classname for tr
  126.         if (classname !== '') {
  127.             tr_obj.className = classname;
  128.         }
  129.         
  130.         // Iterate over td cells
  131.         for (i = 0; i < values.length; i++) {
  132.             td_obj           = that.tdMotherObj.cloneNode(false);
  133.             td_obj.innerHTML = values[i];
  134.             td_obj.className = classNames[i];
  135.             tr_obj.appendChild(td_obj);
  136.         }
  137.         return tr_obj;
  138.     }
  139.  
  140.     /**
  141.      * Create a CSV row string
  142.      *
  143.      * @param {array} values for TD-Elements
  144.      * @param {string} classname: classname of TR-Element
  145.      * @return {string} ;separated list of columns
  146.      */
  147.     function _createCsvRow(values) {
  148.         var i;
  149.         var row = '';
  150.         
  151.         // Iterate over cells
  152.         for (i = 0; i < values.length; i++) {
  153.             if (i !== 0) {
  154.                 row += "\t" + values[i];
  155.             } else {
  156.                 row += values[i];
  157.             }
  158.         }
  159.         return row;
  160.     }
  161.  
  162.     /**
  163.      * Fill a value with preceding zeros
  164.      *
  165.      * @param {string} value
  166.      * @param {integer} length
  167.      * @return {string}
  168.      */
  169.     function _zeroFill(value, fillLength) {
  170.         var i;
  171.         value = value.toString();
  172.         
  173.         for (i = value.length; i < fillLength; i++) {
  174.             value = '0' + value;
  175.         }
  176.         return value;
  177.     }
  178.     
  179.     /**
  180.      * Convert seconds to HH:MM:SS
  181.      *
  182.      * @param {integer}
  183.      * @return {string}
  184.      */
  185.     function _secondsToString(secs) {
  186.         var hours, minutes;
  187.         
  188.         // transform to hours, minutes and seconds
  189.         hours = Math.floor(secs / 60 / 60);
  190.         secs -= (hours * 60 * 60);
  191.         
  192.         minutes = Math.floor(secs / 60);
  193.         secs   -= (minutes * 60);
  194.         
  195.         hours   = hours.toString();
  196.         minutes = minutes.toString();
  197.         secs    = secs.toString();
  198.         
  199.         // shift single values with a 0
  200.         if (hours.length < 2) {
  201.             hours = '0' + hours;
  202.         }
  203.         if (minutes.length < 2) {
  204.             minutes = '0' + minutes;
  205.         }
  206.         if (secs.length < 2) {
  207.             secs = '0' + secs;
  208.         }
  209.         
  210.         return hours + ':' + minutes + ':' + secs;
  211.     }
  212.     
  213.     /**
  214.      * Convert a string in format "HH:MM:SS" to seconds
  215.      *
  216.      * @param {string}
  217.      * @return {integer}
  218.      */
  219.     function _getDurationInSecs(str) {
  220.         var secs = 0;
  221.         var time = str.split(':');
  222.         
  223.         secs += parseInt(time[0] * 60 * 60, 10);
  224.         secs += parseInt(time[1] * 60, 10);
  225.         secs += parseInt(time[2], 10);
  226.         
  227.         return secs;
  228.     }
  229.     
  230.     /**
  231.      * Convert a string in german date format to a date object.
  232.      *
  233.      * @param {string} txt
  234.      * @return {date}
  235.      */
  236.     function _germanDateToDate(txt) {
  237.         var enDate = txt.substr(6, 4) + '/' + txt.substr(3, 2) + '/' + txt.substr(0,2);
  238.         return new Date(enDate);
  239.     }
  240.     
  241.     /**
  242.      * Return german date from a date object.
  243.      *
  244.      * @param {date}
  245.      * @return {string}
  246.      */
  247.     function _dateToGermanDate(dateObj) {
  248.         var newDate = _zeroFill(dateObj.getDate(), 2) + '.' + _zeroFill(dateObj.getMonth() + 1, 2) + '.' + dateObj.getFullYear();
  249.         return newDate;
  250.     }
  251.     
  252.     /**
  253.      * Get the day before today.
  254.      *
  255.      * @see _zeroFill
  256.      * @param {string} str_day
  257.      * @return {date}
  258.      */
  259.     function _getYesterday(day)
  260.     {
  261.         var calday = new Date(day.getTime() - (24 * 60 * 60 * 1000));
  262.         return calday;
  263.     }
  264.     
  265.     /**
  266.      * Get the next day
  267.      *
  268.      * @see _zeroFill
  269.      * @param {string} str_day
  270.      * @return {date}
  271.      */
  272.     function _getTomorrow(day)
  273.     {
  274.         var calday = new Date(day.getTime() + (24 * 60 * 60 * 1000));
  275.         return calday;
  276.     }
  277.     
  278.     /**
  279.      * Set the initial start date for the list display.
  280.      *
  281.      * Search the first of the preceding month starting with today.
  282.      */
  283.     function _setInitialStartDate() {
  284.         var calMonth = new Date().getMonth();
  285.         var calYear  = new Date().getFullYear();
  286.          
  287.         if (calMonth === 0) {
  288.            calMonth = 12;
  289.            calYear -= 1;
  290.         }
  291.         
  292.         that.minDisplayDate = new Date(calYear + '/' + calMonth + '/1');
  293.     }
  294.     
  295.     /**
  296.      * Display the notification area and hide the result table
  297.      */
  298.     function _showNotification(headline, text) {
  299.         if (headline !== '') {
  300.             that.noctificationHObj.innerHTML = headline;
  301.         }
  302.         if (text !== '') {
  303.             that.noctificationTxtObj.innerHTML = text;
  304.         }
  305.         that.noctificationObj.style.display = 'block';
  306.         that.listTableObj.style.display     = 'none';
  307.         that.CSVAreaObj.style.display       = 'none';
  308.     }
  309.     
  310.     /**
  311.      * Display the result table and hide the notification area
  312.      */
  313.     function _showResultTable() {
  314.         that.noctificationObj.style.display = 'none';
  315.         that.listTableObj.style.display     = 'block';
  316.         that.CSVAreaObj.style.display       = 'block';
  317.     }
  318.     
  319.     // -------------------------------------------------------------------------
  320.     // Privileged methods:
  321.     // -------------------------------------------------------------------------
  322.     
  323.     // --------------- Modal panel
  324.  
  325.     /**
  326.      * Show the modal panel
  327.      *
  328.      * @param {string}
  329.      */
  330.     this.pShowModalPanel = function(statusText) {
  331.         if (typeof statusText === 'string') {
  332.             this.modalPanelStatusObj.innerHTML = statusText;
  333.         }
  334.         this.modalPanelObj.style.visibility    = 'visible';
  335.         this.modalPanelBGObj.style.visibility  = 'visible';
  336.     };
  337.  
  338.     /**
  339.      * Hide the modal panel
  340.      */
  341.     this.pHideModalPanel = function() {
  342.         this.modalPanelObj.style.visibility    = 'hidden';
  343.         this.modalPanelBGObj.style.visibility  = 'hidden';
  344.     };
  345.  
  346.     // --------------- Information display
  347.     
  348.     /**
  349.      * Print total of connection costs
  350.      */
  351.     this.pPrintSum = function() {
  352.         this.sumObj.innerHTML = this.sum.toFixed(2);
  353.     };
  354.     
  355.     /**
  356.      * Print total of connection durations
  357.      */
  358.     this.pPrintDuration = function() {
  359.         this.durationObj.innerHTML = _secondsToString(this.duration);
  360.     };
  361.     
  362.     /**
  363.      * Print min and max date to HTML form
  364.      */
  365.     this.pPrintDates = function() {
  366.         var today = new Date();
  367.         this.dateFromObj.value  = _dateToGermanDate(this.minDisplayDate);
  368.         this.dateToObj.value    = _dateToGermanDate(today);
  369.     };
  370.     
  371.     // --------------- List table manipulation
  372.     
  373.     /**
  374.      * Update sort indicators in the table header
  375.      *
  376.      * Sort indicators are set via the id-attribute in a span element in a th-element.
  377.      */
  378.     this.pUpdateTableHeader = function() {
  379.         var i;
  380.         var indicators = document.getElementById('THead').getElementsByTagName('SPAN');
  381.         var mapper = {d_Begin: 0, i_DurationInSec: 6, i_Clock: 5, r_CostPerMin: 3, r_CostPerCall: 4, ca_Provider: 1, ca_PhoneNumber: 2, r_Costs: 7};
  382.         
  383.         // Clear all IDs
  384.         for (i = 0; i < indicators.length; i++) {
  385.             indicators[i].id = '';
  386.         }
  387.         
  388.         // Set new ID
  389.         if (this.sortDirection[this.sortBy] === 'asc') {
  390.             indicators[mapper[this.sortBy]].id = 'focus-down';
  391.         } else {
  392.             indicators[mapper[this.sortBy]].id = 'focus-up';
  393.         }
  394.     };
  395.  
  396.     /**
  397.      * Delete the complete list table
  398.      */
  399.     this.pDeleteTable = function() {
  400.         var i;
  401.         var rows = this.listObj.childNodes;
  402.         
  403.         for (i = this.listObj.childNodes.length-1; i > -1; i--) {
  404.             this.listObj.deleteRow(i);
  405.         }
  406.     };
  407.  
  408.     /**
  409.      * Get the min and max date and set the display flag.
  410.      */
  411.     this.pPrepareDatastore = function() {
  412.         var tr_obj, ds_date, className;
  413.         var classname = '';
  414.         var ds_length = datastore.length;
  415.         var i         = 0;
  416.         var count     = 0;
  417.         eval("var rowRef = window.dataindex_" + fieldindexorder[this.sortBy]);
  418.  
  419.         for (i = 0; i < ds_length; i++) {
  420.             // Prepare display flag
  421.             if (typeof datastore[i][this.datastoreLength] !== 'number') {
  422.                 datastore[i][this.datastoreLength] = 1;
  423.             }
  424.             
  425.             // Get min and max date
  426.             ds_date = _germanDateToDate(datastore[i][fieldindexorder.d_Begin]);
  427.             if (this.minDate === '' || this.minDate > ds_date) {
  428.                 this.minDate = ds_date;
  429.             }
  430.             if (this.maxDate === '' || this.maxDate < ds_date) {
  431.                 this.maxDate = ds_date;
  432.             }
  433.         }
  434.     };
  435.     
  436.     /**
  437.      * Update the list table
  438.      *
  439.      * @param {string}
  440.      */
  441.     this.pUpdateTable = function(row) {
  442.         var tRow;
  443.         var count       = 0;
  444.         var dl          = datastore.length;
  445.         this.sum        = 0;
  446.         this.duration   = 0;
  447.         var i           = 0;
  448.         var subConStore = []; // Temp store for sub connections
  449.         
  450.         eval("var rowRef = window.dataindex_" + fieldindexorder[row]);
  451.         
  452.         for (i = 0; i < dl; i++) {
  453.             if (datastore[rowRef[i]][this.datastoreLength] === 1) {
  454.                 className = count % 2 ? 'alt' : '';
  455.                 
  456.                 // create and fill tr-object
  457.                 tr_obj = _createTableRow([
  458.                     datastore[rowRef[i]][datastoreFields.d_Begin] + " " + datastore[rowRef[i]][datastoreFields.i_Duration],
  459.                     datastore[rowRef[i]][datastoreFields.ca_Provider],
  460.                     datastore[rowRef[i]][datastoreFields.ca_PhoneNumber],
  461.                     datastore[rowRef[i]][datastoreFields.r_CostPerMin],
  462.                     datastore[rowRef[i]][datastoreFields.r_CostPerCall],
  463.                     datastore[rowRef[i]][datastoreFields.i_Clock],
  464.                     _secondsToString(datastore[rowRef[i]][datastoreFields.i_DurationInSec]) + "  ",
  465.                     datastore[rowRef[i]][datastoreFields.r_Costs] + "  "
  466.                     ], className);
  467.                  
  468.                 // differentiate between main- and subconnections
  469.                 if (datastore[rowRef[i]][datastoreFields.b_ChannelBundeled] === 0) {
  470.                     // Mainconnections
  471.                     this.listObj.appendChild(tr_obj);
  472.                     
  473.                     // if there are subconnections then print'em
  474.                     if (subConStore.length > 0) {
  475.                         for (var k = 0; k < subConStore.length; k++) {
  476.                             this.listObj.appendChild(subConStore[k]);
  477.                         }
  478.                         subConStore = [];
  479.                     }
  480.                     
  481.                 } else {
  482.                     // Subconnections
  483.                     
  484.                     // Alter visual presentation by adjusting the classname (in tr-object)
  485.                     // : wait for webprod template
  486.                     this.changeConnectionToSubConnection(tr_obj);
  487.                     
  488.                     // save subconnections temporarily if sortdirection is descending,
  489.                     // otherwise append them directly
  490.                     if (this.sortDirection[this.sortBy] === 'asc') {
  491.                         subConStore.push(tr_obj);
  492.                     } else {
  493.                         this.listObj.appendChild(tr_obj);
  494.                     }
  495.                 }
  496.                 
  497.                 // Build sum of costs
  498.                 this.sum += parseFloat(datastore[rowRef[i]][1].replace(',', '.'), 2);
  499.  
  500.                 // Calculate overall duration
  501.                 this.duration += datastore[rowRef[i]][4];
  502.  
  503.                 count++;
  504.             }
  505.         }
  506.     };
  507.  
  508.     /**
  509.      * Print the result to the output object
  510.      * 
  511.      * This method threads itself according to the action variable, so the modal panel
  512.      * is displayed before the calculation starts.
  513.      * 
  514.      * @param {string} action: showPanel|printTable|hidePanel
  515.      */
  516.     this.pDoPrint = function(action) {
  517.         if (!action) {
  518.             action = 'showPanel';
  519.         }
  520.         
  521.         if (datastore.length === 0) {
  522.             _showNotification('Es liegen bisher keine Verbindungsdaten vor.', '');
  523.         } else if (this.displayedResults === 0) {
  524.             _showNotification('Für Ihre Auswahl konnten keine Verbindungsdaten gefunden werden.', 'Bitte erweitern Sie den Zeitraum über die Filteroptionen oben.');
  525.         } else {
  526.             _showResultTable();
  527.             
  528.             if (action === 'showPanel') {
  529.                 if (this.displayedResults > this.criticalDatastoreLength) {
  530.                     this.pShowModalPanel();
  531.                 }
  532.                 window.setTimeout(
  533.                     function() {
  534.                         that.pDoPrint('printTable');
  535.                     },
  536.                     10);
  537.             }
  538.             if (action === 'printTable') {
  539.                 this.pUpdateTable(this.sortBy);
  540.                 this.pUpdateTableHeader();
  541.                 this.pPrintSum();
  542.                 this.pPrintDuration();
  543.                 this.pPrintDates();
  544.                 
  545.                 window.setTimeout(
  546.                     function() {
  547.                         that.pDoPrint('hidePanel');
  548.                     },
  549.                     10);
  550.             }
  551.             if (action === 'hidePanel') {
  552.                 this.pHideModalPanel();
  553.             }
  554.         }
  555.     };
  556.  
  557.     // --------------- Sort methods
  558.     
  559.     /**
  560.      * Sort the datastore index asc or desc
  561.      *
  562.      * If the same column is clicked again reverse the sort direction.
  563.      * If another column is chosen take the sort direction from the
  564.      * previous column.
  565.      * 
  566.      * @param {integer}
  567.      */
  568.     this.pSort = function(row) {
  569.         eval("var rowRef = window.dataindex_" + fieldindexorder[row]);
  570.  
  571.         if (row === this.sortBy) {
  572.             if (this.sortDirection[row] === 'desc') {
  573.                 this.sortDirection[row] = 'asc';
  574.                 rowRef.reverse();
  575.             } else {
  576.                 this.sortDirection[row] = 'desc';
  577.                 rowRef.reverse();
  578.             }
  579.         } else {
  580.             if (this.sortDirection[row] !== this.sortDirection[this.sortBy]) {
  581.                 rowRef.reverse();
  582.             }
  583.             this.sortDirection[row] = this.sortDirection[this.sortBy];
  584.         }
  585.     };
  586.     
  587.     /**
  588.      * Wrapper for the sort function
  589.      *
  590.      * This method threads itself according to the action variable, so the modal panel
  591.      * is displayed before the calculation starts.
  592.      *
  593.      * @param {object} domObj
  594.      * @param {string} sortType
  595.      * @param {string} action: showPanel|printTable|hidePanel
  596.      */
  597.     this.pDoSort = function(action, row) {
  598.         if (!action) {
  599.             action = 'showPanel';
  600.         }
  601.         
  602.         if (action === 'showPanel') {
  603.             if (this.displayedResults > this.criticalDatastoreLength) {
  604.                 this.pShowModalPanel('Sortiere Tabelle');
  605.             }
  606.             window.setTimeout(
  607.                 function() {
  608.                     that.pDoSort('sort', row);
  609.                 },
  610.                 10);
  611.         }
  612.         
  613.         if (action === 'sort') {
  614.             this.pSort(row);
  615.             this.pDeleteTable();
  616.             this.pUpdateTable(row);
  617.             this.sortBy = row;
  618.             this.pUpdateTableHeader();
  619.             
  620.             window.setTimeout(
  621.                 function() {
  622.                     that.pDoSort('hidePanel', row);
  623.                 },
  624.                 10);
  625.         }
  626.         
  627.         if (action === 'hidePanel') {
  628.             this.pHideModalPanel();
  629.         }
  630.         return false;
  631.     };
  632.     
  633.     // --------------- Select methods
  634.  
  635.     /**
  636.      * Narrow the datastore selection to the users' input
  637.      */
  638.     this.pSelect = function() {
  639.         var i, k;
  640.         var conCost;
  641.         var dl        = datastore.length;
  642.         var takeover  = true;
  643.         var chosenCon = this.selectorObj.value;
  644.         var fulltext  = this.fulltextObj.value;
  645.         var date_from = _germanDateToDate(this.dateFromObj.value);
  646.         var date_to   = _germanDateToDate(this.dateToObj.value);
  647.         var date_cur;
  648.         var ftSearchMinus   = [];
  649.         var ftSearchPlus    = [];
  650.         var ftSearchPlusTmp = [];
  651.         var searchfield     = this.fulltextObj.value;
  652.         
  653.         // Define negative fulltext search criteria
  654.         var negSearch = searchfield.match(/(\s\-{1,}|^\-)(.[^\s]*)/g);
  655.         
  656.         if (negSearch) {
  657.             for (i = 0; i < negSearch.length; i++) {
  658.                 if (negSearch[i].substr(0,1) === '-') {
  659.                     ftSearchMinus.push(negSearch[i].substr(1).toLowerCase());
  660.                 } else {
  661.                     ftSearchMinus.push(negSearch[i].substr(2).toLowerCase());
  662.                 }
  663.                 searchfield = searchfield.replace(negSearch[i], '');
  664.             }
  665.         }
  666.         
  667.         // Define positive fulltext search criteria
  668.         searchfield     = searchfield.replace('+', '');
  669.         ftSearchPlusTmp = searchfield.split(' ');
  670.         
  671.         for (i = 0; i < ftSearchPlusTmp.length; i++) {
  672.             if (ftSearchPlusTmp[i] !== '') {
  673.                 if (ftSearchPlusTmp[i].substr(0,1) === '+') {
  674.                     ftSearchPlus.push(ftSearchPlusTmp[i].substr(1));
  675.                 } else {
  676.                     ftSearchPlus.push(ftSearchPlusTmp[i]);
  677.                 }
  678.             }
  679.         }
  680.         
  681.         this.displayedResults = 0;
  682.         
  683.         for (i = 0; i < dl; i++) {
  684.             // Connection
  685.             if (chosenCon === '*') {
  686.                 takeover = true;
  687.             } else {
  688.                 conCostPerMin  = parseFloat(datastore[i][7].replace(',', '.'));
  689.                 conCostPerCall = parseFloat(datastore[i][10].replace(',', '.'));
  690.                 if (chosenCon === '1') {
  691.                     if (conCostPerCall > 0) {
  692.                         takeover = true;
  693.                     } else {
  694.                         takeover = false;
  695.                     }
  696.                 } else if (chosenCon === '2') {
  697.                     if (conCostPerCall === 0) {
  698.                         takeover = true;
  699.                     } else {
  700.                         takeover = false;
  701.                     }
  702.                 } else if (chosenCon === '3') {
  703.                     if (conCostPerMin > 1.5) {
  704.                         takeover = true;
  705.                     } else {
  706.                         takeover = false;
  707.                     }
  708.                 } else {
  709.                     takeover = false;
  710.                 }
  711.             }
  712.             
  713.             // Date from to
  714.             if (takeover) {
  715.                 date_cur = _germanDateToDate(datastore[i][2]);
  716.                 if (date_cur >= date_from &&
  717.                     date_cur <= date_to) {
  718.                     takeover = true;
  719.                 } else {
  720.                     takeover = false;
  721.                 }
  722.             }
  723.             
  724.             // Fulltext
  725.             if (takeover && this.fulltextObj.value !== '') {
  726.                 for (m = 0; m < ftSearchMinus.length; m++) {
  727.                     if (datastore[i][5].toLowerCase().indexOf(ftSearchMinus[m]) > -1) {
  728.                         takeover = false;
  729.                     } else if (datastore[i][9].toLowerCase().indexOf(ftSearchMinus[m]) > -1) {
  730.                         takeover = false;
  731.                     }
  732.                 }
  733.  
  734.                 if (takeover) {
  735.                     tmp_takeover = true;
  736.                     for (m = 0; m < ftSearchPlus.length; m++) {
  737.                         if ((datastore[i][5].toLowerCase().indexOf(ftSearchPlus[m].toLowerCase()) > -1 ||
  738.                             datastore[i][9].indexOf(ftSearchPlus[m].toLowerCase()) > -1) &&
  739.                             tmp_takeover) {
  740.                             tmp_takeover = true;
  741.                         } else {
  742.                             tmp_takeover = false;
  743.                         }
  744.                     }
  745.                     
  746.                     if (tmp_takeover) {
  747.                         takeover = true;
  748.                     } else {
  749.                         takeover = false;
  750.                     }
  751.                 }
  752.             }
  753.             
  754.             if (takeover) {
  755.                 datastore[i][this.datastoreLength] = 1;
  756.                 this.displayedResults++;
  757.             } else {
  758.                 datastore[i][this.datastoreLength] = 0;
  759.             }
  760.         }
  761.     };
  762.     
  763.     /**
  764.      * Wrapper for the select function
  765.      *
  766.      * This method threads itself according to the action variable, so the modal panel
  767.      * is displayed before the calculation starts.
  768.      *
  769.      * @param {string} action
  770.      */
  771.     this.pDoSelect = function(action) {
  772.         if (datastore.length > 0) {
  773.             if (!action) {
  774.                 action = 'showPanel';
  775.             }
  776.             
  777.             if (action === 'showPanel') {
  778.                 if (this.displayedResults > this.criticalDatastoreLength) {
  779.                     this.pShowModalPanel('Durchsuche Tabelle');
  780.                 }
  781.                 window.setTimeout(
  782.                     function() {
  783.                         that.pDoSelect('select');
  784.                     },
  785.                     10);
  786.             }
  787.             
  788.             if (action === 'select') {
  789.                 this.pSelect();
  790.                 
  791.                 if (this.displayedResults === 0) {
  792.                     _showNotification('Für Ihre Auswahl konnten keine Verbindungsdaten gefunden werden.', 'Bitte ändern Sie den Zeitraum, in dem gesucht werden soll oder heben Sie die Sucheinschränkungen auf.');
  793.                 } else {
  794.                     _showResultTable();
  795.                     this.pDeleteTable();
  796.                     this.pUpdateTable(this.sortBy);
  797.                     this.pPrintSum();
  798.                     this.pPrintDuration();
  799.                 }
  800.                 
  801.                 window.setTimeout(
  802.                     function() {
  803.                         that.pDoSelect('hidePanel');
  804.                     },
  805.                     10);
  806.             }
  807.             
  808.             if (action === 'hidePanel') {
  809.                 this.pHideModalPanel();
  810.             }
  811.         }
  812.         return false;
  813.     };
  814.     
  815.     // --------------- Calendar popups
  816.  
  817.     /**
  818.      * Calendar functionality: Show dateFrom-Calendar and adjust non-selectable days
  819.      */
  820.     this.pSelectFromDate = function() {
  821.         if (this.minDate) {
  822.             var endDate = this.dateToObj.value;
  823.             endDate = _germanDateToDate(endDate);
  824.             
  825.             // hide select box
  826.             if (document.all) {
  827.                 this.selectorObj.style.visibility = 'hidden';
  828.             }
  829.             
  830.             calFrom.clearDisabledDays();
  831.             calFrom.addDisabledDates(null, formatDate(_getYesterday(this.minDate), 'yyyy-MM-dd'));
  832.             calFrom.addDisabledDates(formatDate(_getTomorrow(endDate), 'yyyy-MM-dd'), null);
  833.             calFrom.select(this.dateFromObj,'DateFrom','dd.MM.yyyy');
  834.             calFrom.refresh();
  835.         }
  836.     };
  837.  
  838.     /**
  839.      * Calendar functionality: Show dateTo-Calendar and adjust non-selectable days
  840.      */
  841.     this.pSelectToDate = function() {
  842.         if (this.minDate) {
  843.             var startDate = this.dateFromObj.value;
  844.             var today     = new Date();
  845.             startDate     = _germanDateToDate(startDate);
  846.             
  847.             // hide select box
  848.             if (document.all) {
  849.                 this.selectorObj.style.visibility = 'hidden';
  850.             }
  851.             
  852.             calTo.clearDisabledDays();
  853.             calTo.addDisabledDates(null, formatDate(_getYesterday(startDate), 'yyyy-MM-dd'));
  854.             calTo.addDisabledDates(formatDate(_getTomorrow(today), 'yyyy-MM-dd'), null);
  855.             calTo.select(this.dateToObj,'DateTo','dd.MM.yyyy');
  856.             calTo.refresh();
  857.         }
  858.     };
  859.     
  860.     // --------------- CSV export
  861.     
  862.     /**
  863.      * Do the CSV export
  864.      */
  865.     this.pDoCsvExport = function() {
  866.         var tRow;
  867.         var count       = 0;
  868.         var dl          = datastore.length;
  869.         var i           = 0;
  870.         this.sum        = 0;
  871.         this.duration   = 0;
  872.         var output      = '';
  873.         
  874.         this.selectorObj.style.visibility   = 'hidden';
  875.         this.CSVBox.style.display           = 'block';
  876.         
  877.         eval("var rowRef = window.dataindex_" + fieldindexorder[this.sortBy]);
  878.         
  879.         for (i = 0; i < dl; i++) {
  880.             if (datastore[rowRef[i]][this.datastoreLength] === 1) {
  881.                 output += (_createCsvRow([datastore[rowRef[i]][2] + " " + datastore[rowRef[i]][3],
  882.                                     datastore[rowRef[i]][5],
  883.                                     ""+datastore[rowRef[i]][9],
  884.                                     datastore[rowRef[i]][7],
  885.                                     datastore[rowRef[i]][10],
  886.                                     datastore[rowRef[i]][6],
  887.                                     datastore[rowRef[i]][4],
  888.                                     datastore[rowRef[i]][1]
  889.                                     ]) + "\r\n");
  890.                 
  891.                 // Build sum of costs
  892.                 this.sum += parseFloat(datastore[rowRef[i]][1].replace(',', '.'), 2);
  893.  
  894.                 // Calculate overall duration
  895.                 this.duration += _getDurationInSecs(datastore[rowRef[i]][fieldindexorder.i_DurationInSec]);
  896.  
  897.                 count++;
  898.             }
  899.         }
  900.         
  901.         this.CSVTextarea.value = output;
  902.         
  903.         return false;
  904.     };
  905.     
  906.     this.pPrintSysData = function() {
  907.         var datafields = ['smversion', 'datefrom', 'username', 'os', 'cpu', 'ram', 'modem', 'dialstring'];
  908.         var i;
  909.         
  910.         //prepare data fields
  911.         sysdata.datefrom = _dateToGermanDate(new Date(sysdata.datefrom.substr(0, 10).replace(/-/g, '/'))) + ', ' + sysdata.datefrom.substr(11, 5) + ' Uhr';
  912.         
  913.         
  914.         for (i in datafields) {
  915.             if (!sysdata[datafields[i]] || sysdata[datafields[i]] === '') {
  916.                 sysdata[datafields[i]] = '---';
  917.             }
  918.             
  919.             document.getElementById('Sys' + i).innerHTML = sysdata[datafields[i]];
  920.         }
  921.     };
  922.     
  923.     // Call constructor
  924.     _init();
  925. };
  926.  
  927. // -----------------------------------------------------------------------------
  928. // Public methods:
  929. // -----------------------------------------------------------------------------
  930.  
  931. /**
  932.  * Print the result list
  933.  */
  934. webde.dienste.kostenprotokoll.prototype.printList = function() {
  935.     // Display notification if there are more than 3000 datafields
  936.     var obj = document.getElementById('DataNotification');
  937.     if (sysdata.dataCount > 3000) {
  938.         obj.style.display = 'block';
  939.     } else {
  940.         obj.style.display = 'none';
  941.     }
  942.     
  943.     this.pDoPrint('showPanel');
  944. };
  945.  
  946. /**
  947.  * Get Sysdata and print it to the sysdata-list
  948.  */
  949. webde.dienste.kostenprotokoll.prototype.printSysdata = function() {
  950.     this.pPrintSysData();
  951. };
  952.  
  953. webde.dienste.kostenprotokoll.prototype.closeCSVWindow = function() {
  954.     this.CSVBox.style.display           = 'none';
  955.     this.selectorObj.style.visibility   = 'visible';
  956.     return false;
  957. };
  958.  
  959. /**
  960.  * Changes a tr-html-object so that it represents a subconnection.
  961.  * 
  962.  * @param {Object} trObj
  963.  */
  964. webde.dienste.kostenprotokoll.prototype.changeConnectionToSubConnection = function(trObj) {
  965.     var tdCell;
  966.     
  967.     if (tdCell = trObj.getElementsByTagName('TD')[0]) {
  968.         var tdCellValue = tdCell.innerHTML;
  969.         var tdCellNewValue = '<table border="0" cellspacing="0" cellpadding="0" width="140" style="margin-bottom:0px;"><tr><td class="kanalbuendelung" style="width:12px;"></td><td class="kanalbuendelung" style="width:1px;"><img src="img/linie.gif" width="5" height="24" alt="" border="0" /></td><td class="kanalbuendelung" style="width:4px;"></td><td class="kanalbuendelung" style="width:118px;">'+tdCellValue+'</td></tr></table>';
  970.         tdCell.innerHTML = tdCellNewValue;
  971.     }
  972. }
  973.